{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/anaconda3/envs/py35_int64/lib/python3.5/site-packages/h5py/__init__.py:36: FutureWarning: Conversion of the second argument of issubdtype from `float` to `np.floating` is deprecated. In future, it will be treated as `np.float64 == np.dtype(float).type`.\n",
      "  from ._conv import register_converters as _register_converters\n",
      "WARNING:tf_encrypted:Falling back to insecure randomness since the required custom op could not be found for the installed version of TensorFlow. Fix this by compiling custom ops. Missing file was '/Users/yanndupis/Documents/dropoutlabs/tfe_v2/tf-encrypted/tf_encrypted/operations/secure_random/secure_random_module_tf_1.13.1.so'\n"
     ]
    }
   ],
   "source": [
    "import tensorflow as tf\n",
    "\n",
    "import tf_encrypted as tfe\n",
    "from tf_encrypted.keras import backend as KE\n",
    "from tf_encrypted.keras.losses import BinaryCrossentropy\n",
    "from tf_encrypted.keras.optimizers import SGD\n",
    "\n",
    "from common import DataOwner\n",
    "\n",
    "import sys\n",
    "sys.path.append('../')\n",
    "from utils import print_in_notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "num_features = 10\n",
    "training_set_size = 2000\n",
    "test_set_size = 100\n",
    "batch_size = 100\n",
    "steps_per_epoch = (training_set_size // batch_size)\n",
    "epochs = 20"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "WARNING: The TensorFlow contrib module will not be included in TensorFlow 2.0.\n",
      "For more information, please see:\n",
      "  * https://github.com/tensorflow/community/blob/master/rfcs/20180907-contrib-sunset.md\n",
      "  * https://github.com/tensorflow/addons\n",
      "If you depend on functionality not listed there, please file an issue.\n",
      "\n",
      "WARNING:tensorflow:From /anaconda3/envs/py35_int64/lib/python3.5/site-packages/tensorflow/python/data/ops/dataset_ops.py:1419: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From /anaconda3/envs/py35_int64/lib/python3.5/site-packages/tensorflow/python/data/ops/dataset_ops.py:1419: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "Colocations handled automatically by placer.\n"
     ]
    }
   ],
   "source": [
    "data_owner = DataOwner('data-owner',\n",
    "                       num_features,\n",
    "                       training_set_size,\n",
    "                       test_set_size,\n",
    "                       batch_size)\n",
    "\n",
    "x_train, y_train = data_owner.provide_training_data()\n",
    "x_test, y_test = data_owner.provide_testing_data()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [],
   "source": [
    "@tfe.local_computation('data-owner')\n",
    "def compute_accuracy(y_pred, y_test):\n",
    "    correct_prediction = tf.equal(tf.round(y_pred), y_test)\n",
    "    accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))\n",
    "    print_op = print_in_notebook(accuracy)\n",
    "    return print_op"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Define Model"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [],
   "source": [
    "model = tfe.keras.Sequential()\n",
    "model.add(tfe.keras.layers.Dense(1, batch_input_shape=[batch_size, num_features]))\n",
    "model.add(tfe.keras.layers.Activation('sigmoid'))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "scrolled": false
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "INFO:tf_encrypted:Players: ['server0', 'server1', 'server2', 'data-owner']\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 1/20\n",
      "2000/2000 [==============================] - 2s 1ms/step - loss: 0.7092\n",
      "Epoch 2/20\n",
      "2000/2000 [==============================] - 0s 74us/step - loss: 0.6598\n",
      "Epoch 3/20\n",
      "2000/2000 [==============================] - 0s 73us/step - loss: 0.6133\n",
      "Epoch 4/20\n",
      "2000/2000 [==============================] - 0s 85us/step - loss: 0.5761\n",
      "Epoch 5/20\n",
      "2000/2000 [==============================] - 0s 77us/step - loss: 0.5484\n",
      "Epoch 6/20\n",
      "2000/2000 [==============================] - 0s 76us/step - loss: 0.5196\n",
      "Epoch 7/20\n",
      "2000/2000 [==============================] - 0s 79us/step - loss: 0.4918\n",
      "Epoch 8/20\n",
      "2000/2000 [==============================] - 0s 94us/step - loss: 0.4795\n",
      "Epoch 9/20\n",
      "2000/2000 [==============================] - 0s 83us/step - loss: 0.4606\n",
      "Epoch 10/20\n",
      "2000/2000 [==============================] - 0s 96us/step - loss: 0.4458\n",
      "Epoch 11/20\n",
      "2000/2000 [==============================] - 0s 74us/step - loss: 0.4285\n",
      "Epoch 12/20\n",
      "2000/2000 [==============================] - 0s 73us/step - loss: 0.4139\n",
      "Epoch 13/20\n",
      "2000/2000 [==============================] - 0s 75us/step - loss: 0.4078\n",
      "Epoch 14/20\n",
      "2000/2000 [==============================] - 0s 74us/step - loss: 0.3957\n",
      "Epoch 15/20\n",
      "2000/2000 [==============================] - 0s 75us/step - loss: 0.3832\n",
      "Epoch 16/20\n",
      "2000/2000 [==============================] - 0s 76us/step - loss: 0.3777\n",
      "Epoch 17/20\n",
      "2000/2000 [==============================] - 0s 76us/step - loss: 0.3692\n",
      "Epoch 18/20\n",
      "2000/2000 [==============================] - 0s 72us/step - loss: 0.3627\n",
      "Epoch 19/20\n",
      "2000/2000 [==============================] - 0s 74us/step - loss: 0.3637\n",
      "Epoch 20/20\n",
      "2000/2000 [==============================] - 0s 72us/step - loss: 0.3479\n",
      "WARNING:tensorflow:From ../utils.py:9: py_func (from tensorflow.python.ops.script_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "tf.py_func is deprecated in TF V2. Instead, use\n",
      "    tf.py_function, which takes a python function which manipulates tf eager\n",
      "    tensors instead of numpy arrays. It's easy to convert a tf eager tensor to\n",
      "    an ndarray (just call tensor.numpy()) but having access to eager tensors\n",
      "    means `tf.py_function`s can use accelerators such as GPUs as well as\n",
      "    being differentiable using a gradient tape.\n",
      "    \n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:tensorflow:From ../utils.py:9: py_func (from tensorflow.python.ops.script_ops) is deprecated and will be removed in a future version.\n",
      "Instructions for updating:\n",
      "tf.py_func is deprecated in TF V2. Instead, use\n",
      "    tf.py_function, which takes a python function which manipulates tf eager\n",
      "    tensors instead of numpy arrays. It's easy to convert a tf eager tensor to\n",
      "    an ndarray (just call tensor.numpy()) but having access to eager tensors\n",
      "    means `tf.py_function`s can use accelerators such as GPUs as well as\n",
      "    being differentiable using a gradient tape.\n",
      "    \n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0.96\n"
     ]
    }
   ],
   "source": [
    "sess = KE.get_session()\n",
    "sess.run([data_owner.initializer])\n",
    "\n",
    "model.compile(optimizer=SGD(lr=0.01),\n",
    "              loss=BinaryCrossentropy())\n",
    "\n",
    "# Train\n",
    "model.fit(x_train,\n",
    "          y_train,\n",
    "          epochs=epochs,\n",
    "          steps_per_epoch=steps_per_epoch)\n",
    "\n",
    "# evaluate\n",
    "y_pred = model(x_test)\n",
    "sess.run(compute_accuracy(y_pred, y_test))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
